package tld.course.lesson2 
{
	/**
	 * ...
	 * @author wvxvw
	 */
	public class Grid
	{
		public function get width():uint { return this._width; }
		
		public function get height():uint { return this._height; }
		
		private const _cells:Vector.<uint> = new <uint>[];
		private var _width:uint;
		private var _height:uint;
		
		public function Grid(width:uint = 1, height:uint = 1) 
		{
			super();
			this._width = width;
			this._height = height;
			this.init(width * height);
		}
		
		public function serveFood(foodKind:uint):void
		{
			var cells:uint;
			
			for each (var cell:uint in this._cells) if (!cell) cells++;
			cells = Math.random() * cells;
			for (var i:int = this._cells.length - 1; i > -1; i--)
			{
				if (!this._cells[i])
				{
					cells--;
					if (cells <= 0)
					{
						this._cells[i] = foodKind;
						break;
					}
				}
			}
		}
		
		public function eachFood(callback:Function):void
		{
			var cell:uint;
			
			for (var i:int = this._cells.length - 1; i > -1; i--)
			{
				cell = this._cells[i];
				if (cell > 1) callback(cell, i);
			}
		}
		
		public function canMove(x:uint, y:uint):Boolean
		{
			return this.isInBounds(x, y) && 
				this.isPassableCell(this._cells[x + y * this._width]);
		}
		
		public function get(x:uint, y:uint):uint
		{
			this.checkBounds(x, y);
			return this._cells[x + y * this._width];
		}
		
		public function set(x:uint, y:uint, value:uint):void
		{
			this.checkBounds(x, y);
			this._cells[x + y * this._width] = value;
		}
		
		private function isInBounds(x:uint, y:uint):Boolean
		{
			return x < this._width && y < this._height;
		}
		
		private function isPassableCell(cell:uint):Boolean
		{
			// 0   - empty cell.
			// > 1 - anything the snake can eat.
			// this function may be modified later to add more kinds of obstacles.
			return cell != 1;
		}
		
		private function checkBounds(x:uint, y:uint):void
		{
			if (!this.isInBounds(x, y)) throw new ArgumentError("Out of bounds");
		}
		
		private function init(size:uint):void
		{
			while (size-- > 0) this._cells.push(0);
		}
	}

}